home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Mail / pine3.92 / pico / basic.c < prev    next >
C/C++ Source or Header  |  1996-03-14  |  21KB  |  871 lines

  1. #if    !defined(lint) && !defined(DOS)
  2. static char rcsid[] = "$Id: basic.c,v 4.25 1996/03/15 07:41:11 hubert Exp $";
  3. #endif
  4. /*
  5.  * Program:    Cursor manipulation functions
  6.  *
  7.  *
  8.  * Michael Seibel
  9.  * Networks and Distributed Computing
  10.  * Computing and Communications
  11.  * University of Washington
  12.  * Administration Builiding, AG-44
  13.  * Seattle, Washington, 98195, USA
  14.  * Internet: mikes@cac.washington.edu
  15.  *
  16.  * Please address all bugs and comments to "pine-bugs@cac.washington.edu"
  17.  *
  18.  *
  19.  * Pine and Pico are registered trademarks of the University of Washington.
  20.  * No commercial use of these trademarks may be made without prior written
  21.  * permission of the University of Washington.
  22.  * 
  23.  * Pine, Pico, and Pilot software and its included text are Copyright
  24.  * 1989-1996 by the University of Washington.
  25.  * 
  26.  * The full text of our legal notices is contained in the file called
  27.  * CPYRIGHT, included with this distribution.
  28.  *
  29.  */
  30. /*
  31.  * The routines in this file move the cursor around on the screen. They
  32.  * compute a new value for the cursor, then adjust ".". The display code
  33.  * always updates the cursor location, so only moves between lines, or
  34.  * functions that adjust the top line in the window and invalidate the
  35.  * framing, are hard.
  36.  */
  37. #include        <stdio.h>
  38. #include        <ctype.h>
  39. #include    "osdep.h"
  40. #include        "pico.h"
  41. #include    "estruct.h"
  42. #include        "edef.h"
  43. #include        "efunc.h"
  44.  
  45.  
  46. #ifdef    ANSI
  47.     int getgoal(struct LINE *);
  48. #else
  49.     int getgoal();
  50. #endif
  51.  
  52.  
  53. /*
  54.  * Move the cursor to the
  55.  * beginning of the current line.
  56.  * Trivial.
  57.  */
  58. gotobol(f, n)
  59. int f, n;
  60. {
  61.     curwp->w_doto  = 0;
  62.     return (TRUE);
  63. }
  64.  
  65. /*
  66.  * Move the cursor backwards by "n" characters. If "n" is less than zero call
  67.  * "forwchar" to actually do the move. Otherwise compute the new cursor
  68.  * location. Error if you try and move out of the buffer. Set the flag if the
  69.  * line pointer for dot changes.
  70.  */
  71. backchar(f, n)
  72. int             f;
  73. register int    n;
  74. {
  75.     register LINE   *lp;
  76.  
  77.     if (n < 0)
  78.       return (forwchar(f, -n));
  79.  
  80.     while (n--) {
  81.     if (curwp->w_doto == 0) {
  82.         if ((lp=lback(curwp->w_dotp)) == curbp->b_linep){
  83.         if(Pmaster && Pmaster->headents)
  84.             /*
  85.              * go up into editing the mail header if on 
  86.              * the top line and the user hits the left arrow!!!
  87.              *
  88.              * if the editor returns anything except -1, the 
  89.              * user requested something special, so let 
  90.              * pico know...
  91.              */
  92.           return(HeaderEditor(2, 1));
  93.         else
  94.           return (FALSE);
  95.         }
  96.  
  97.         curwp->w_dotp  = lp;
  98.         curwp->w_doto  = llength(lp);
  99.         curwp->w_flag |= WFMOVE;
  100.     } else
  101.       curwp->w_doto--;
  102.     }
  103.  
  104.     return (TRUE);
  105. }
  106.  
  107.  
  108. /*
  109.  * Move the cursor to the end of the current line. Trivial. No errors.
  110.  */
  111. gotoeol(f, n)
  112. int f, n;
  113. {
  114.     curwp->w_doto  = llength(curwp->w_dotp);
  115.     return (TRUE);
  116. }
  117.  
  118.  
  119. /*
  120.  * Move the cursor forwwards by "n" characters. If "n" is less than zero call
  121.  * "backchar" to actually do the move. Otherwise compute the new cursor
  122.  * location, and move ".". Error if you try and move off the end of the
  123.  * buffer. Set the flag if the line pointer for dot changes.
  124.  */
  125. forwchar(f, n)
  126. int             f;
  127. register int    n;
  128. {
  129.     if (n < 0)
  130.       return (backchar(f, -n));
  131.  
  132.     while (n--) {
  133.     if (curwp->w_doto == llength(curwp->w_dotp)) {
  134.         if (curwp->w_dotp == curbp->b_linep)
  135.           return (FALSE);
  136.  
  137.         curwp->w_dotp  = lforw(curwp->w_dotp);
  138.         curwp->w_doto  = 0;
  139.         curwp->w_flag |= WFMOVE;
  140.     }
  141.     else
  142.       curwp->w_doto++;
  143.     }
  144.     
  145.     return (TRUE);
  146. }
  147.  
  148.  
  149. /*
  150.  * move to a particular line.
  151.  * argument (n) must be a positive integer for
  152.  * this to actually do anything
  153.  */
  154. gotoline(f, n)
  155. int f, n;
  156. {
  157.     if (n < 1)        /* if a bogus argument...then leave */
  158.       return(FALSE);
  159.  
  160.     /* first, we go to the start of the buffer */
  161.     curwp->w_dotp  = lforw(curbp->b_linep);
  162.     curwp->w_doto  = 0;
  163.     return(forwline(f, n-1));
  164. }
  165.  
  166.  
  167. /*
  168.  * Goto the beginning of the buffer. Massive adjustment of dot. This is
  169.  * considered to be hard motion; it really isn't if the original value of dot
  170.  * is the same as the new value of dot. Normally bound to "M-<".
  171.  */
  172. gotobob(f, n)
  173. int f, n;
  174. {
  175.     curwp->w_dotp  = lforw(curbp->b_linep);
  176.     curwp->w_doto  = 0;
  177.     curwp->w_flag |= WFHARD;
  178.     return (TRUE);
  179. }
  180.  
  181.  
  182. /*
  183.  * Move to the end of the buffer. Dot is always put at the end of the file
  184.  * (ZJ). The standard screen code does most of the hard parts of update.
  185.  * Bound to "M->".
  186.  */
  187. gotoeob(f, n)
  188. int f, n;
  189. {
  190.     curwp->w_dotp  = curbp->b_linep;
  191.     curwp->w_doto  = 0;
  192.     curwp->w_flag |= WFHARD;
  193.     return (TRUE);
  194. }
  195.  
  196.  
  197. /*
  198.  * Move forward by full lines. If the number of lines to move is less than
  199.  * zero, call the backward line function to actually do it. The last command
  200.  * controls how the goal column is set. Bound to "C-N". No errors are
  201.  * possible.
  202.  */
  203. forwline(f, n)
  204. int f, n;
  205. {
  206.     register LINE   *dlp;
  207.  
  208.     if (n < 0)
  209.       return (backline(f, -n));
  210.  
  211.     if ((lastflag&CFCPCN) == 0)             /* Reset goal if last   */
  212.       curgoal = getccol(FALSE);       /* not C-P or C-N       */
  213.  
  214.     thisflag |= CFCPCN;
  215.     dlp = curwp->w_dotp;
  216.     while (n-- && dlp!=curbp->b_linep)
  217.       dlp = lforw(dlp);
  218.  
  219.     curwp->w_dotp  = dlp;
  220.     curwp->w_doto  = getgoal(dlp);
  221.     curwp->w_flag |= WFMOVE;
  222.     return (TRUE);
  223. }
  224.  
  225.  
  226. /*
  227.  * This function is like "forwline", but goes backwards. The scheme is exactly
  228.  * the same. Check for arguments that are less than zero and call your
  229.  * alternate. Figure out the new line and call "movedot" to perform the
  230.  * motion. No errors are possible. Bound to "C-P".
  231.  */
  232. backline(f, n)
  233. int f, n;
  234. {
  235.     register LINE   *dlp;
  236.     register int    status = 0;
  237.  
  238.     if (n < 0)
  239.       return (forwline(f, -n));
  240.  
  241.     if(Pmaster && Pmaster->headents){
  242.     /*
  243.      * go up into editing the mail header if on the top line
  244.      * and the user hits the up arrow!!!
  245.      */
  246.     if (lback(curwp->w_dotp) == curbp->b_linep)
  247.       /*
  248.        * if the editor returns anything except -1 then the user
  249.        * has requested something special, so let pico know...
  250.        */
  251.       return(HeaderEditor(1, 1));
  252.     }
  253.  
  254.     if ((lastflag&CFCPCN) == 0)             /* Reset goal if the    */
  255.       curgoal = getccol(FALSE);       /* last isn't C-P, C-N  */
  256.  
  257.     thisflag |= CFCPCN;
  258.     dlp = curwp->w_dotp;
  259.     while (n-- && lback(dlp)!=curbp->b_linep)
  260.       dlp = lback(dlp);
  261.  
  262.     curwp->w_dotp  = dlp;
  263.     curwp->w_doto  = getgoal(dlp);
  264.     curwp->w_flag |= WFMOVE;
  265.     return (TRUE);
  266. }
  267.  
  268.  
  269. /*
  270.  * go back to the begining of the current paragraph
  271.  * here we look for a <NL><NL> or <NL><TAB> or <NL><SPACE>
  272.  * combination to delimit the begining of a paragraph    
  273.  */
  274. gotobop(f, n)
  275. int f, n;    /* default Flag & Numeric argument */
  276. {
  277.     register int txt;
  278.  
  279.     if (n < 0)    /* the other way...*/
  280.       return(gotoeop(f, -n));
  281.  
  282.     while (n-- > 0) {    /* for each one asked for */
  283.  
  284.     /* is there text on the current line? */
  285.     for(txt = llength(curwp->w_dotp);
  286.         txt > 0 && isspace(lgetc(curwp->w_dotp, txt-1).c);
  287.         txt--)
  288.       ;
  289.  
  290.     if(!txt)
  291.       /* scan backward until we do find text */
  292.       while(lback(curwp->w_dotp) != curbp->b_linep
  293.         && (!llength(curwp->w_dotp)
  294.             || curwp->w_doto == llength(curwp->w_dotp)
  295.             || isspace(lgetc(curwp->w_dotp, curwp->w_doto).c)))
  296.         backchar(FALSE, 1);
  297.  
  298.     /* scan line by line until we come to a line ending with
  299.      * a <NL><NL> or <NL><TAB> or <NL><SPACE>
  300.      */
  301.     while(lback(curwp->w_dotp) != curbp->b_linep
  302.           && llength(lback(curwp->w_dotp))
  303.           && lgetc(curwp->w_dotp, 0).c != TAB
  304.           && lgetc(curwp->w_dotp, 0).c != ' ')
  305.       curwp->w_dotp = lback(curwp->w_dotp);
  306.  
  307.     if(n){
  308.         /* keep looking */
  309.         if(lback(curwp->w_dotp) == curbp->b_linep)
  310.           break;
  311.         else
  312.           curwp->w_dotp = lback(curwp->w_dotp);
  313.  
  314.         curwp->w_doto = 0;
  315.     }
  316.     else{
  317.       /* leave cursor on first word in para */
  318.         curwp->w_doto = 0;
  319.         while(isspace(lgetc(curwp->w_dotp, curwp->w_doto).c))
  320.           if(++curwp->w_doto >= llength(curwp->w_dotp)){
  321.           curwp->w_doto = 0;
  322.           curwp->w_dotp = lforw(curwp->w_dotp);
  323.           if(curwp->w_dotp == curbp->b_linep)
  324.             break;
  325.           }
  326.     }
  327.     }
  328.  
  329.     curwp->w_flag |= WFMOVE;    /* force screen update */
  330.     return(TRUE);
  331. }
  332.  
  333.  
  334. /* 
  335.  * go forword to the end of the current paragraph
  336.  * here we look for a <NL><NL> or <NL><TAB> or <NL><SPACE>
  337.  * combination to delimit the begining of a paragraph
  338.  */
  339. gotoeop(f, n)
  340. int f, n;    /* default Flag & Numeric argument */
  341.  
  342. {
  343.     register int txt;
  344.  
  345.     if (n < 0)    /* the other way...*/
  346.       return(gotobop(f, -n));
  347.  
  348.     while (n-- > 0) {    /* for each one asked for */
  349.  
  350.     /* is there text on the current line? */
  351.     for(txt = llength(curwp->w_dotp);
  352.         txt > 0 && isspace(lgetc(curwp->w_dotp, txt-1).c);
  353.         txt--)
  354.       ;
  355.  
  356.     if(!txt)
  357.       /* scan forword until we do find text */
  358.       while(curwp->w_dotp != curbp->b_linep
  359.         && (!llength(curwp->w_dotp)
  360.             || curwp->w_doto == llength(curwp->w_dotp)
  361.             || isspace(lgetc(curwp->w_dotp, curwp->w_doto).c)))
  362.         forwchar(FALSE, 1);
  363.  
  364.     /* scan line by line until we come to a line ending with
  365.      * a <NL><NL> or <NL><TAB> or <NL><SPACE>
  366.      */
  367.     while(curwp->w_dotp != curbp->b_linep
  368.           && llength(lforw(curwp->w_dotp))
  369.           && lgetc(lforw(curwp->w_dotp), 0).c != TAB
  370.           && lgetc(lforw(curwp->w_dotp), 0).c != ' ')
  371.       curwp->w_dotp = lforw(curwp->w_dotp);
  372.  
  373.     curwp->w_doto = llength(curwp->w_dotp);
  374.  
  375.     /* still looking? */
  376.     if(n){
  377.         if(curwp->w_dotp == curbp->b_linep)
  378.           break;
  379.         else
  380.           curwp->w_dotp = lforw(curwp->w_dotp);
  381.  
  382.         curwp->w_doto = 0;
  383.     }
  384.     }
  385.  
  386.     curwp->w_flag |= WFMOVE;    /* force screen update */
  387.     return(curwp->w_dotp != curbp->b_linep);
  388. }
  389.  
  390. /*
  391.  * This routine, given a pointer to a LINE, and the current cursor goal
  392.  * column, return the best choice for the offset. The offset is returned.
  393.  * Used by "C-N" and "C-P".
  394.  */
  395. getgoal(dlp)
  396. register LINE   *dlp;
  397. {
  398.     register int    c;
  399.     register int    col;
  400.     register int    newcol;
  401.     register int    dbo;
  402.  
  403.     col = 0;
  404.     dbo = 0;
  405.     while (dbo != llength(dlp)) {
  406.     c = lgetc(dlp, dbo).c;
  407.     newcol = col;
  408.     if (c == '\t')
  409.       newcol |= 0x07;
  410.     else if (c<0x20 || c==0x7F)
  411.       ++newcol;
  412.  
  413.     ++newcol;
  414.     if (newcol > curgoal)
  415.       break;
  416.  
  417.     col = newcol;
  418.     ++dbo;
  419.     }
  420.  
  421.     return (dbo);
  422. }
  423.  
  424.  
  425.  
  426. /*
  427.  * Scroll the display forward (up) n lines.
  428.  */
  429. scrollforw (n, movedot)
  430. register int    n;
  431. int        movedot;
  432. {
  433.     register LINE   *lp;
  434.     LINE        *lp2;
  435.     register int    nl;
  436.     int            i;
  437.  
  438.     nl = n;
  439.     lp = curwp->w_linep;
  440.     while (n-- && lp!=curbp->b_linep)
  441.       lp = lforw(lp);
  442.  
  443.     if (movedot) {            /* Move dot to top of page. */
  444.     curwp->w_dotp  = lp;
  445.     curwp->w_doto  = 0;
  446.     }
  447.  
  448.     curwp->w_flag |= WFHARD;
  449.     if(lp == curbp->b_linep)
  450.       return(TRUE);
  451.     else
  452.       curwp->w_linep = lp;
  453.  
  454.     /*
  455.      * if the header is open, close it ...
  456.      */
  457.     if(Pmaster && Pmaster->headents && ComposerTopLine != COMPOSER_TOP_LINE){
  458.     n -= ComposerTopLine - COMPOSER_TOP_LINE;
  459.     ToggleHeader(0);
  460.     }
  461.  
  462.     /*
  463.      * scroll down from the top the same number of lines we've moved 
  464.      * forward
  465.      */
  466.     if(optimize)
  467.       scrollup(curwp, -1, nl-n-1);
  468.  
  469.     if(!movedot){
  470.     /* Requested to not move the dot.  Look for the dot in the current
  471.      * window.  loop through all lines, stop when at end of window
  472.      * or endof buffer.  If the dot is found, it can stay where it
  473.      * is, otherwise we do need to move it.
  474.      */
  475.     movedot = TRUE;
  476.     for (    lp2 = lp, i = 0; 
  477.         lp2 != curbp->b_linep && i < curwp->w_ntrows;  
  478.         lp2 = lforw(lp2), ++i) {
  479.         if (curwp->w_dotp == lp2) {
  480.          movedot = FALSE;
  481.          break;
  482.         }
  483.         }
  484.     if (movedot) {
  485.         /* Dot not found in window.  Move to first line of window. */
  486.         curwp->w_dotp  = lp;
  487.         curwp->w_doto  = 0;
  488.         }
  489.     }
  490.  
  491.     return (TRUE);
  492. }
  493.  
  494.  
  495. /*
  496.  * Scroll forward by a specified number of lines, or by a full page if no
  497.  * argument. Bound to "C-V". The "2" in the arithmetic on the window size is
  498.  * the overlap; this value is the default overlap value in ITS EMACS. Because
  499.  * this zaps the top line in the display window, we have to do a hard update.
  500.  */
  501. forwpage(f, n)
  502. int             f;
  503. register int    n;
  504. {
  505.  
  506.     if (f == FALSE) {
  507.     n = curwp->w_ntrows - 2;        /* Default scroll.      */
  508.     if (n <= 0)                     /* Forget the overlap   */
  509.       n = 1;                  /* if tiny window.      */
  510.     } else if (n < 0)
  511.       return (backpage(f, -n));
  512. #if     CVMVAS
  513.     else                                    /* Convert from pages   */
  514.       n *= curwp->w_ntrows;           /* to lines.            */
  515. #endif
  516.     return (scrollforw (n, TRUE));
  517. }
  518.  
  519.  
  520. /*
  521.  * Scroll back (down) number of lines.  
  522.  */
  523. scrollback (n, movedot)
  524. register int    n;
  525. int        movedot;
  526. {
  527.     register LINE   *lp, *tp;
  528.     register int    nl;
  529.     int             status = 0;
  530.     int            i;
  531.  
  532.     if(Pmaster && Pmaster->headents){
  533.     /*
  534.      * go up into editing the mail header if on the top line
  535.      * and the user hits the up arrow!!!
  536.      */
  537.     if (lback(curwp->w_dotp) == curbp->b_linep){
  538.         /*
  539.          * if the editor returns anything except -1 then the user
  540.          * has requested something special, so let pico know...
  541.          */
  542.         return(HeaderEditor(1, 1));
  543.     }
  544.     }
  545.  
  546.     /*
  547.      * Count back the number of lines requested.
  548.      */
  549.     nl = n;
  550.     lp = curwp->w_linep;
  551.     while (n-- && lback(lp)!=curbp->b_linep)
  552.       lp = lback(lp);
  553.  
  554.     curwp->w_linep = lp;
  555.     curwp->w_flag |= WFHARD;
  556.  
  557.     /*
  558.      * scroll down from the top the same number of lines we've moved 
  559.      * forward
  560.      *
  561.      * This isn't too cool, but it has to be this way so we can 
  562.      * gracefully scroll in the message header
  563.      */
  564.     if(Pmaster && Pmaster->headents){
  565.     if((lback(lp)==curbp->b_linep) && (ComposerTopLine==COMPOSER_TOP_LINE))
  566.       n -= entry_line(1000, TRUE); /* never more than 1000 headers */
  567.     if(nl-n-1 < curwp->w_ntrows)
  568.       if(optimize)
  569.         scrolldown(curwp, -1, nl-n-1);
  570.     }
  571.     else
  572.       if(optimize)
  573.     scrolldown(curwp, -1, nl-n-1);
  574.  
  575.     if(Pmaster && Pmaster->headents){
  576.     /*
  577.      * if we're at the top of the page, and the header is closed, 
  578.      * open it ...
  579.      */
  580.     if((lback(lp) == curbp->b_linep) 
  581.        && (ComposerTopLine == COMPOSER_TOP_LINE)){
  582.         ToggleHeader(1);
  583.         movecursor(ComposerTopLine, 0);
  584.     }
  585.     }
  586.     
  587.     /*
  588.      * Decide if we move the dot or not.  Calculation done AFTER deciding
  589.      * if we display the header because that will change the number of
  590.      * lines on the screen.
  591.      */
  592.     if (movedot) {
  593.     /* Dot gets put at top of window. */
  594.     curwp->w_dotp  = curwp->w_linep;
  595.     curwp->w_doto  = 0;
  596.     }
  597.     else {
  598.     /* Requested not to move dot, but we do need to keep in on
  599.      * the screen.  Verify that it is still in the range of lines
  600.      * visable in the window.  Loop from the first line to the
  601.      * last line, until we reach the end of the buffer or the end
  602.      * of the window.  If we find the dot, then we don't need
  603.      * to move it. */
  604.     movedot = TRUE;
  605.     for (    tp = curwp->w_linep, i = 0; 
  606.         tp != curbp->b_linep && i < curwp->w_ntrows;  
  607.         tp = lforw(tp), ++i) {
  608.         if (curwp->w_dotp == tp) {
  609.          movedot = FALSE;
  610.          break;
  611.         }
  612.         }
  613.     if (movedot) {
  614.         /* Dot not found in window.  Move to last line of window. */
  615.         curwp->w_dotp  = lback (tp);
  616.         curwp->w_doto  = 0;
  617.         }
  618.     }
  619.  
  620.     return (TRUE);
  621. }
  622.  
  623.  
  624.  
  625.  
  626. /*
  627.  * This command is like "forwpage", but it goes backwards. The "2", like
  628.  * above, is the overlap between the two windows. The value is from the ITS
  629.  * EMACS manual. Bound to "M-V". We do a hard update for exactly the same
  630.  * reason.
  631.  */
  632. backpage(f, n)
  633. int             f;
  634. register int    n;
  635. {
  636.  
  637.     if (f == FALSE) {
  638.     n = curwp->w_ntrows - 2;        /* Default scroll.      */
  639.     if (n <= 0)                     /* Don't blow up if the */
  640.       n = 1;                  /* window is tiny.      */
  641.     } else if (n < 0)
  642.       return (forwpage(f, -n));
  643. #if     CVMVAS
  644.     else                                    /* Convert from pages   */
  645.       n *= curwp->w_ntrows;           /* to lines.            */
  646. #endif
  647.     return (scrollback (n, TRUE));
  648. }
  649.  
  650.  
  651.  
  652. scrollupline (f, n)
  653. int f, n;
  654. {
  655.     return (scrollback (1, FALSE));
  656. }
  657.  
  658.  
  659. scrolldownline (f, n)
  660. int f, n;
  661. {
  662.     return (scrollforw (1, FALSE));
  663. }
  664.  
  665.  
  666.  
  667. /*
  668.  * Scroll to a position.
  669.  */
  670. scrollto (f, n)
  671. int f, n;
  672. {
  673. #ifdef _WINDOWS
  674.     long    scrollLine;
  675.     LINE    *lp;
  676.     int        i;
  677.     
  678.     scrollLine = mswin_getscrollto ();
  679.     
  680.     /*
  681.      * Starting at the first data line in the buffer, step forward
  682.      * 'scrollLine' lines to find the new top line.  It is a circular
  683.      * list of buffers, so watch for the first line to reappear.  if
  684.      * it does, we have some sort of internal error, abort scroll
  685.      * operation.  Also watch for NULL, just in case.
  686.      */
  687.     lp = lforw (curbp->b_linep);
  688.     for (i = 0; i < scrollLine && lp != curbp->b_linep && lp != NULL; ++i)
  689.     lp = lforw(lp);
  690.  
  691.     if (lp == curbp->b_linep || lp == NULL)
  692.     return (FALSE);                    /* Whoops! */
  693.     
  694.  
  695.     /* Set the new top line for the window and flag a redraw. */
  696.     curwp->w_linep = lp;
  697.     curwp->w_dotp  = lp;
  698.     curwp->w_doto  = 0;
  699.     curwp->w_flag |= WFHARD;
  700.     
  701.     if(Pmaster && Pmaster->headents){
  702.     /*
  703.      * If we are at the top of the page and header not open, open it.
  704.      * If we are not at the top of the page and the header is open,
  705.      * close it.
  706.      */
  707.     if((lback(lp) == curbp->b_linep) 
  708.        && (ComposerTopLine == COMPOSER_TOP_LINE)){
  709.         ToggleHeader(1);
  710.         movecursor(ComposerTopLine, 0);
  711.     }
  712.     else if((lback(lp) != curbp->b_linep) 
  713.        && (ComposerTopLine != COMPOSER_TOP_LINE)){
  714.        ToggleHeader (0);
  715.         }
  716.     }
  717.  
  718.     return (TRUE);
  719. #endif
  720. }
  721.  
  722.  
  723.  
  724. /*
  725.  * Set the mark in the current window to the value of "." in the window. No
  726.  * errors are possible. Bound to "M-.".  If told to set an already set mark
  727.  * unset it.
  728.  */
  729. setmark(f, n)
  730. int f, n;
  731. {
  732.     if(!curwp->w_markp){
  733.         curwp->w_markp = curwp->w_dotp;
  734.         curwp->w_marko = curwp->w_doto;
  735.     emlwrite("Mark Set", NULL);
  736.     }
  737.     else{
  738.     /* clear inverse chars between here and dot */
  739.     markregion(0);
  740.     curwp->w_markp = NULL;
  741.     emlwrite("Mark UNset", NULL);
  742.     }
  743.  
  744. #ifdef    _WINDOWS
  745.     mswin_allowcopycut(curwp->w_markp ? kremove : NULL);
  746. #endif
  747.     return (TRUE);
  748. }
  749.  
  750.  
  751. /*
  752.  * Swap the values of "." and "mark" in the current window. This is pretty
  753.  * easy, bacause all of the hard work gets done by the standard routine
  754.  * that moves the mark about. The only possible error is "no mark". Bound to
  755.  * "C-X C-X".
  756.  */
  757. swapmark(f, n)
  758. int f, n;
  759. {
  760.     register LINE   *odotp;
  761.     register int    odoto;
  762.  
  763.     if (curwp->w_markp == NULL) {
  764.     if(Pmaster == NULL)
  765.       emlwrite("No mark in this window", NULL);
  766.     return (FALSE);
  767.     }
  768.  
  769.     odotp = curwp->w_dotp;
  770.     odoto = curwp->w_doto;
  771.     curwp->w_dotp  = curwp->w_markp;
  772.     curwp->w_doto  = curwp->w_marko;
  773.     curwp->w_markp = odotp;
  774.     curwp->w_marko = odoto;
  775.     curwp->w_flag |= WFMOVE;
  776.     return (TRUE);
  777. }
  778.  
  779.  
  780. /*
  781.  * Set the mark in the current window to the value of "." in the window. No
  782.  * errors are possible. Bound to "M-.".  If told to set an already set mark
  783.  * unset it.
  784.  */
  785. setimark(f, n)
  786. int f, n;
  787. {
  788.     curwp->w_imarkp = curwp->w_dotp;
  789.     curwp->w_imarko = curwp->w_doto;
  790.     return(TRUE);
  791. }
  792.  
  793.  
  794. /*
  795.  * Swap the values of "." and "mark" in the current window. This is pretty
  796.  * easy, bacause all of the hard work gets done by the standard routine
  797.  * that moves the mark about. The only possible error is "no mark". Bound to
  798.  * "C-X C-X".
  799.  */
  800. swapimark(f, n)
  801. int f, n;
  802. {
  803.     register LINE   *odotp;
  804.     register int    odoto;
  805.  
  806.     if (curwp->w_imarkp == NULL) {
  807.     if(Pmaster == NULL)
  808.       emlwrite("Programmer botch! No mark in this window", NULL);
  809.     return (FALSE);
  810.     }
  811.  
  812.     odotp = curwp->w_dotp;
  813.     odoto = curwp->w_doto;
  814.     curwp->w_dotp  = curwp->w_imarkp;
  815.     curwp->w_doto  = curwp->w_imarko;
  816.     curwp->w_imarkp = odotp;
  817.     curwp->w_imarko = odoto;
  818.     curwp->w_flag |= WFMOVE;
  819.     return (TRUE);
  820. }
  821.  
  822.  
  823.  
  824. #ifdef MOUSE
  825.  
  826. /*
  827.  * Handle a mouse down.
  828.  */
  829. mousepress (f, n)
  830. int f, n;
  831. {
  832.     MOUSEPRESS    mp;
  833.     LINE    *lp;
  834.     int    i;
  835.  
  836.  
  837.     mouse_get_last (NULL, &mp);
  838.  
  839.  
  840.     lp = curwp->w_linep;
  841.     i = mp.row - ((Pmaster && Pmaster->headents) ? ComposerTopLine : 2);
  842.     if (i < 0) {
  843.     if (Pmaster) {
  844.         /* Clear existing region. */
  845.         if (curwp->w_markp)
  846.         setmark(0,1);    
  847.  
  848.         /* Move to top of document before editing header. */
  849.         curwp->w_dotp = curwp->w_linep;
  850.         curwp->w_doto = 0;
  851.         curwp->w_flag |= WFMOVE;
  852.         update ();                /* And update. */
  853.  
  854.         return (HeaderEditor (1, 1));
  855.         }
  856.     }
  857.     else {
  858.     while(i-- && lp != curbp->b_linep)
  859.       lp = lforw(lp);
  860.  
  861.     curgoal = mp.col;
  862.     curwp->w_dotp = lp;
  863.     curwp->w_doto = getgoal(lp);
  864.     curwp->w_flag |= WFMOVE;
  865.  
  866.     if(mp.doubleclick)
  867.         setmark(0, 1);
  868.     }
  869. }
  870. #endif
  871.